package com.nuoniu.sibanyun.service.so.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.entity.bo.*;
import com.nuoniu.sibanyun.entity.erp.ErpInvoiceType;
import com.nuoniu.sibanyun.entity.erp.ErpNumberSet;
import com.nuoniu.sibanyun.entity.so.*;
import com.nuoniu.sibanyun.mapper.erp.ErpNumberSetMapper;
import com.nuoniu.sibanyun.mapper.so.VSaleInvoiceMainMapper;
import com.nuoniu.sibanyun.service.crm.ICrmGoodsService;
import com.nuoniu.sibanyun.service.erp.IErpAccountService;
import com.nuoniu.sibanyun.service.erp.IErpInvoiceTypeService;
import com.nuoniu.sibanyun.service.erp.IErpNumberSetService;
import com.nuoniu.sibanyun.service.erp.IErpVoucherDesignService;
import com.nuoniu.sibanyun.service.so.IVSaleInvoiceDetailService;
import com.nuoniu.sibanyun.service.so.IVSaleInvoiceMainService;
import com.nuoniu.sibanyun.service.utils.ErpUtils;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 销售发票主表 服务实现类
 * </p>
 *
 * @author 小啊刚
 * @since 2020-12-07
 */
@Service
public class VSaleInvoiceMainServiceImpl extends ServiceImpl<VSaleInvoiceMainMapper, VSaleInvoiceMain> implements IVSaleInvoiceMainService {

    @Autowired
    private IErpNumberSetService numberSetService;
    @Autowired
    private ErpNumberSetMapper numberSetMapper;
    @Autowired
    private IVSaleInvoiceDetailService saleInvoiceDetailService;
    @Autowired
    private IErpAccountService accountService;
    @Autowired
    private IErpVoucherDesignService erpVoucherDesignService;
    @Autowired
    private IErpInvoiceTypeService erpInvoiceTypeService;
    @Autowired
    private ICrmGoodsService crmGoodsService;



    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveInvoice(VSaleInvoiceMain saleInvoiceMain) {
        Boolean isNewMain = false;
        List<VSaleInvoiceDetail> orderDetailList = saleInvoiceMain.getOrderDetailList();
        if(null == orderDetailList)throw new NuoNiuException("单据明细不能为空");
        Long mainId = saleInvoiceMain.getId();
        UserInfo userInfo = UserThreadLocal.get();
        VSaleInvoiceMain oldVSaleInvoiceMain = null;
        Integer businessType = saleInvoiceMain.getBusinessType();
        Integer invoiceTypeId = saleInvoiceMain.getInvoiceTypeId();
        ErpInvoiceType invoiceType = erpInvoiceTypeService.getById(invoiceTypeId);
        Integer type = invoiceType.getType();
//        if(( (null != businessType && 98 == businessType) || 0 == type) && orderDetailList.stream().anyMatch(f->f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0)){
//            throw new NuoNiuException("单据明细错误：退货业务 和 负数发票类型的明细数量不能为正数");
//        }
        if(mainId == null) {
            isNewMain = true;
            String code = getCode();
            if(StringUtils.isBlank(code)) {
                throw new NuoNiuException("单据编号已上限");
            }
            //校验详情（详情不能有ID）
            boolean isHaveId = orderDetailList.stream().anyMatch(f -> null != f.getId());
            if(isHaveId)throw new NuoNiuException("单据明细错误：不能新增已经存在的明细记录");
            saleInvoiceMain.setVoucherState(-1);
            saleInvoiceMain.setVoucherCode(code);
            saleInvoiceMain.setAccountId(accountService.getCurrentAccountId());
            saleInvoiceMain.setCompanyId(userInfo.getCompanyId());
            saleInvoiceMain.setCreateUserId(userInfo.getUserId());
            saleInvoiceMain.setCreateUserName(userInfo.getRealName());
        }else {
            //校验详情（详情不能有其他单据的明细ID）
            boolean isHaveErrorId = orderDetailList.stream().anyMatch(f -> null != f.getOrderId() && !mainId.toString().equals(f.getOrderId().toString()));
            if(isHaveErrorId)throw new NuoNiuException("单据明细错误：不能修改其他单据的明细记录");
            oldVSaleInvoiceMain = getById(mainId);
            Integer voucherState = oldVSaleInvoiceMain.getVoucherState();
            if(null != voucherState && voucherState > 0){
                throw new NuoNiuException("已审核,不能修改");
            }
            /**************  修改权限 *******************/
            if(!crmGoodsService.isHaveOperationRight(oldVSaleInvoiceMain.getCreateUserId().longValue())){
                throw new NuoNiuException("你没有权限操作该记录");
            }

            saleInvoiceMain.setUpdateDate(LocalDateTime.now());
            saleInvoiceMain.setUpdateUserId(userInfo.getUserId());
            saleInvoiceMain.setUpdateUserName(userInfo.getRealName());
            saleInvoiceMain.setAccountId(oldVSaleInvoiceMain.getAccountId());
            saleInvoiceMain.setSourceVoucherCode(oldVSaleInvoiceMain.getSourceVoucherCode());
            saleInvoiceMain.setSourceVoucherId(oldVSaleInvoiceMain.getSourceVoucherId());
            saleInvoiceMain.setSourceVoucherType(oldVSaleInvoiceMain.getSourceVoucherType());
            saleInvoiceMain.setSourceVoucherDate(oldVSaleInvoiceMain.getSourceVoucherDate());
            //不可更新字段
            saleInvoiceMain.setVoucherCode(null);
        }
        saleInvoiceMain.setCumExecuteQuantity(null);
        saleInvoiceMain.setCumRetQuantity(null);
        // 校验 明细数量
//        if( (null != businessType && 98 == businessType) || 0 == type ){
//            boolean isOk = saleInvoiceMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) < 0));
//            if(isOk)throw new NuoNiuException("明细数量必须小于0");
//        }else{
//            boolean isOk = saleInvoiceMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0));
//            if(isOk)throw new NuoNiuException("明细数量必须大于0");
//        }
        boolean isOk = saleInvoiceMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0));
        if(isOk)throw new NuoNiuException("明细数量必须大于0");
        //计算 明细物料 总数
        BigDecimal totalQuantity =  saleInvoiceMain.getOrderDetailList().stream().map(VSaleInvoiceDetail::getBaseQuantity).reduce(BigDecimal.ZERO,BigDecimal::add);
        saleInvoiceMain.setTotalQuantity(totalQuantity.abs());

        Boolean result = this.saveOrUpdate(saleInvoiceMain);
        if(result) {
            List<Long> detailIds = new ArrayList<>();
            orderDetailList.forEach(p -> {
                p.setCompanyId(userInfo.getCompanyId());
                p.setAccountId(saleInvoiceMain.getAccountId());
                p.setOrderId(saleInvoiceMain.getId().intValue());
                p.setSourceVoucherCode(saleInvoiceMain.getSourceVoucherCode());
                p.setSourceVoucherType(saleInvoiceMain.getSourceVoucherType());
                p.setSourceVoucherId(saleInvoiceMain.getSourceVoucherId());
                p.setSourceVoucherDate(saleInvoiceMain.getSourceVoucherDate());
                //添加 不删除的明细ID
                if(p.getId() != null) {
                    detailIds.add(p.getId());
                }
            });
            boolean isDealDelete = false;
            if (null != mainId){
                //删除明细
                QueryWrapper wrapper = new QueryWrapper();
                wrapper.eq("order_id", mainId);
                if(detailIds != null && detailIds.size() > 0) {
                    wrapper.notIn("id", detailIds);
                }
                isDealDelete = saleInvoiceDetailService.remove(wrapper);
            }
            //保存单据明细表
            saleInvoiceDetailService.saveOrUpdateBatch(orderDetailList);
            // *** 如果 来源订单不为空,校验
            if(null != saleInvoiceMain.getSourceVoucherId()){
                if(isDealDelete)throw new NuoNiuException("有来源的单据不能删除明细");
                if(!"SaleDelivery".equals(saleInvoiceMain.getSourceVoucherType()))throw new NuoNiuException("销售发票的来源单，只能是销售发货单");
                VoucherInvoiceMainBo voucherMainBo = new VoucherInvoiceMainBo();
                BeanUtils.copyProperties(saleInvoiceMain,voucherMainBo);
                voucherMainBo.setIsNewMain(isNewMain);
                List<VoucherInvoiceDetailBo> voucherDetailBos = new ArrayList<>();
                saleInvoiceMain.getOrderDetailList().forEach(detail->{
                    VoucherInvoiceDetailBo voucherDetailBo = new VoucherInvoiceDetailBo();
                    voucherDetailBos.add(voucherDetailBo);
                    BeanUtils.copyProperties(detail,voucherDetailBo);
                });
                VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
                voucherSearchBo.setSourceVoucherId(saleInvoiceMain.getSourceVoucherId());
                voucherSearchBo.setSourceVoucherType(saleInvoiceMain.getSourceVoucherType());
                voucherSearchBo.setVoucherId(saleInvoiceMain.getId().intValue());
                voucherSearchBo.setVoucherType("SaleInvoice");
                erpVoucherDesignService.calculateInvoiceVoucher(voucherMainBo,voucherDetailBos,voucherSearchBo);

            }
        }
    }

    @Override
    public String getCode() {
        Integer currentAccountId = accountService.getCurrentAccountId();
        UserInfo userInfo = UserThreadLocal.get();
        ErpNumberSet numberSet = numberSetMapper.getByCode("SaleInvoice", userInfo.getCompanyId(), currentAccountId);
        String dateStr = numberSet.getMedian() == 1 ? "%Y-%m-%d" : "%Y-%m";
        String code = baseMapper.getCode(userInfo.getCompanyId(), dateStr);
        return numberSetService.getCode(numberSet, code);
    }

    @Override
    public List<VSaleInvoiceMain> getBySourceId(Long id) {
        return baseMapper.getBySourceId(id);
    }

    @Override
    public void submit(Long id, Integer status) {
        if(null == id || null == status || (null != status && (status > 0 || status < -1 )))throw new NuoNiuException("参数错误");
        UserInfo userInfo = UserThreadLocal.get();
        VSaleInvoiceMain saleInvoiceMain = this.getById(id);
        if( null == saleInvoiceMain)throw new NuoNiuException("记录不存在");
        //校验状态
        Integer voucherState = saleInvoiceMain.getVoucherState();
        /**  统一校验 提交状态 */
        ErpUtils.checkSubmitStatus(voucherState,status);
        //提交
        saleInvoiceMain.setVoucherState(status);
        saleInvoiceMain.setSubmitDate(LocalDateTime.now());
        saleInvoiceMain.setSubmitUserId(userInfo.getUserId());
        saleInvoiceMain.setSubmitUserName(userInfo.getRealName());
        this.updateById(saleInvoiceMain);
    }

    @Override
    public void examine(Long id, Integer status) {
        if(null == id || null == status ||  (status > 1 || status < 0) )throw new NuoNiuException("参数错误");
        UserInfo userInfo = UserThreadLocal.get();
        VSaleInvoiceMain vSaleInvoiceMain = getById(id);
        if(vSaleInvoiceMain == null) {
            throw new NuoNiuException("单据不存在");
        }
        BigDecimal cumExecuteQuantity = vSaleInvoiceMain.getCumExecuteQuantity();
        Integer voucherState = vSaleInvoiceMain.getVoucherState();
        /** 统一校验 审核状态*/
        ErpUtils.checkExamineStatus(voucherState,status,cumExecuteQuantity);
        vSaleInvoiceMain.setVoucherState(status);
        vSaleInvoiceMain.setReviewerDate(LocalDateTime.now());
        vSaleInvoiceMain.setReviewerUserId(userInfo.getUserId());
        vSaleInvoiceMain.setReviewerUserName(userInfo.getRealName());
        updateById(vSaleInvoiceMain);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteById(Long id) {
        UserInfo userInfo = UserThreadLocal.get();
        VSaleInvoiceMain saleInvoiceMain = getById(id);
        if(null == saleInvoiceMain)throw new NuoNiuException("删除失败，记录不存在");
        /**************  修改权限 *******************/
        if(!crmGoodsService.isHaveOperationRight(saleInvoiceMain.getCreateUserId().longValue())){
            throw new NuoNiuException("你没有权限操作该记录");
        }
        // *** 如果 来源订单不为空,校验
        if(null != saleInvoiceMain.getSourceVoucherId()){
            VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
            voucherSearchBo.setCalculateType(2);
            voucherSearchBo.setSourceVoucherId(saleInvoiceMain.getSourceVoucherId());
            voucherSearchBo.setSourceVoucherType(saleInvoiceMain.getSourceVoucherType());
            voucherSearchBo.setVoucherId(saleInvoiceMain.getId().intValue());
            voucherSearchBo.setVoucherType("SaleInvoice");
            //查询 明细
            List<VSaleInvoiceDetail> orderDetails = saleInvoiceDetailService.getDetailsByOrderId(id);
            VoucherInvoiceMainBo voucherMainBo = new VoucherInvoiceMainBo();
            BeanUtils.copyProperties(saleInvoiceMain,voucherMainBo);
            List<VoucherInvoiceDetailBo> voucherDetailBos = new ArrayList<>();
            orderDetails.forEach(detail->{
                VoucherInvoiceDetailBo voucherDetailBo = new VoucherInvoiceDetailBo();
                voucherDetailBos.add(voucherDetailBo);
                BeanUtils.copyProperties(detail,voucherDetailBo);
            });
            erpVoucherDesignService.calculateInvoiceVoucher(voucherMainBo,voucherDetailBos,voucherSearchBo);
            removeById(id);
            saleInvoiceDetailService.deleteByOrderId(id);

        }


    }

    @Override
    public Integer getByInvoiceType(String ids) {
        return baseMapper.getByInvoiceType(ids);
    }

    @Override
    @Async
    public void updateInvoiceType(ErpInvoiceType invoiceType) {
        baseMapper.updateInvoiceType(invoiceType);
    }

    @Override
    public BigDecimal getAmount(Long id) {
        return baseMapper.getAmount(id);
    }
}
